home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / _archvrs / dos / source / aspitape / getdate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-26  |  37.7 KB  |  1,508 lines

  1.  
  2. # line 2 "getdate.y"
  3. /* $Revision: 2.1 $
  4. **
  5. **  Originally written by Steven M. Bellovin <smb@research.att.com> while
  6. **  at the University of North Carolina at Chapel Hill.  Later tweaked by
  7. **  a couple of people on Usenet.  Completely overhauled by Rich $alz
  8. **  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
  9. **  send any email to Rich.
  10. **
  11. **  This grammar has eight shift/reduce conflicts.
  12. **
  13. **  This code is in the public domain and has no copyright.
  14. */
  15. /* SUPPRESS 287 on yaccpar_sccsid *//* Unusd static variable */
  16. /* SUPPRESS 288 on yyerrlab *//* Label unused */
  17.  
  18. #ifdef __GNUC__
  19. #define alloca __builtin_alloca
  20. #else
  21. #ifdef sparc
  22. #include <alloca.h>
  23. #else
  24. #ifdef _AIX /* for Bison */
  25. #pragma alloca
  26. #else
  27. char *alloca ();
  28. #endif
  29. #endif
  30. #endif
  31.  
  32. #include <stdio.h>
  33. #include <ctype.h>
  34.  
  35. #if    defined(vms)
  36. #include <types.h>
  37. #include <time.h>
  38. #else
  39. #include <sys/types.h>
  40. #if    defined(USG)
  41. /*
  42. **  Uncomment the next line if you need to do a tzset() call to set the
  43. **  timezone, and don't have ftime().  Some SystemV releases, I think.
  44. */
  45. /*#define NEED_TZSET */
  46. struct timeb {
  47.     time_t        time;        /* Seconds since the epoch    */
  48.     unsigned short    millitm;    /* Field not used        */
  49.     short        timezone;
  50.     short        dstflag;    /* Field not used        */
  51. };
  52. #else
  53. #include <sys/timeb.h>
  54. #endif    /* defined(USG) */
  55. #if    defined(BSD4_2) || defined(BSD4_1C)
  56. #include <sys/time.h>
  57. #else
  58. #include <time.h>
  59. #endif    /* defined(BSD4_2) */
  60. #endif    /* defined(vms) */
  61.  
  62. #if defined (STDC_HEADERS) || defined (USG)
  63. #include <string.h>
  64. #endif
  65.  
  66. extern struct tm    *localtime();
  67.  
  68. #define yyparse getdate_yyparse
  69. #define yylex getdate_yylex
  70. #define yyerror getdate_yyerror
  71.  
  72. #if    !defined(lint) && !defined(SABER)
  73. static char RCS[] =
  74.     "$Header: str2date.y,v 2.1 90/09/06 08:15:06 cronan Exp $";
  75. #endif    /* !defined(lint) && !defined(SABER) */
  76.  
  77.  
  78. #define EPOCH        1970
  79. #define HOUR(x)        (x * 60)
  80. #define SECSPERDAY    (24L * 60L * 60L)
  81.  
  82.  
  83. /*
  84. **  An entry in the lexical lookup table.
  85. */
  86. typedef struct _TABLE {
  87.     char    *name;
  88.     int        type;
  89.     time_t    value;
  90. } TABLE;
  91.  
  92.  
  93. /*
  94. **  Daylight-savings mode:  on, off, or not yet known.
  95. */
  96. typedef enum _DSTMODE {
  97.     DSTon, DSToff, DSTmaybe
  98. } DSTMODE;
  99.  
  100. /*
  101. **  Meridian:  am, pm, or 24-hour style.
  102. */
  103. typedef enum _MERIDIAN {
  104.     MERam, MERpm, MER24
  105. } MERIDIAN;
  106.  
  107.  
  108. /*
  109. **  Global variables.  We could get rid of most of these by using a good
  110. **  union as the yacc stack.  (This routine was originally written before
  111. **  yacc had the %union construct.)  Maybe someday; right now we only use
  112. **  the %union very rarely.
  113. */
  114. static char    *yyInput;
  115. static DSTMODE    yyDSTmode;
  116. static time_t    yyDayOrdinal;
  117. static time_t    yyDayNumber;
  118. static int    yyHaveDate;
  119. static int    yyHaveDay;
  120. static int    yyHaveRel;
  121. static int    yyHaveTime;
  122. static int    yyHaveZone;
  123. static time_t    yyTimezone;
  124. static time_t    yyDay;
  125. static time_t    yyHour;
  126. static time_t    yyMinutes;
  127. static time_t    yyMonth;
  128. static time_t    yySeconds;
  129. static time_t    yyYear;
  130. static MERIDIAN    yyMeridian;
  131. static time_t    yyRelMonth;
  132. static time_t    yyRelSeconds;
  133.  
  134.  
  135. # line 135 "getdate.y"
  136. typedef union  {
  137.     time_t        Number;
  138.     enum _MERIDIAN    Meridian;
  139. } YYSTYPE;
  140. # define tAGO 257
  141. # define tDAY 258
  142. # define tDAYZONE 259
  143. # define tID 260
  144. # define tMERIDIAN 261
  145. # define tMINUTE_UNIT 262
  146. # define tMONTH 263
  147. # define tMONTH_UNIT 264
  148. # define tSEC_UNIT 265
  149. # define tSNUMBER 266
  150. # define tUNUMBER 267
  151. # define tZONE 268
  152. #define yyclearin yychar = -1
  153. #define yyerrok yyerrflag = 0
  154. extern int yychar;
  155. extern int yyerrflag;
  156. #ifndef YYMAXDEPTH
  157. #define YYMAXDEPTH 150
  158. #endif
  159. YYSTYPE yylval, yyval;
  160. typedef int yytabelem;
  161. # define YYERRCODE 256
  162.  
  163. # line 331 "getdate.y"
  164.  
  165.  
  166. /* Month and day table. */
  167. static TABLE    MonthDayTable[] = {
  168.     { "january",    tMONTH,  1 },
  169.     { "february",    tMONTH,  2 },
  170.     { "march",        tMONTH,  3 },
  171.     { "april",        tMONTH,  4 },
  172.     { "may",        tMONTH,  5 },
  173.     { "june",        tMONTH,  6 },
  174.     { "july",        tMONTH,  7 },
  175.     { "august",        tMONTH,  8 },
  176.     { "september",    tMONTH,  9 },
  177.     { "sept",        tMONTH,  9 },
  178.     { "october",    tMONTH, 10 },
  179.     { "november",    tMONTH, 11 },
  180.     { "december",    tMONTH, 12 },
  181.     { "sunday",        tDAY, 0 },
  182.     { "monday",        tDAY, 1 },
  183.     { "tuesday",    tDAY, 2 },
  184.     { "tues",        tDAY, 2 },
  185.     { "wednesday",    tDAY, 3 },
  186.     { "wednes",        tDAY, 3 },
  187.     { "thursday",    tDAY, 4 },
  188.     { "thur",        tDAY, 4 },
  189.     { "thurs",        tDAY, 4 },
  190.     { "friday",        tDAY, 5 },
  191.     { "saturday",    tDAY, 6 },
  192.     { NULL }
  193. };
  194.  
  195. /* Time units table. */
  196. static TABLE    UnitsTable[] = {
  197.     { "year",        tMONTH_UNIT,    12 },
  198.     { "month",        tMONTH_UNIT,    1 },
  199.     { "fortnight",    tMINUTE_UNIT,    14 * 24 * 60 },
  200.     { "week",        tMINUTE_UNIT,    7 * 24 * 60 },
  201.     { "day",        tMINUTE_UNIT,    1 * 24 * 60 },
  202.     { "hour",        tMINUTE_UNIT,    60 },
  203.     { "minute",        tMINUTE_UNIT,    1 },
  204.     { "min",        tMINUTE_UNIT,    1 },
  205.     { "second",        tSEC_UNIT,    1 },
  206.     { "sec",        tSEC_UNIT,    1 },
  207.     { NULL }
  208. };
  209.  
  210. /* Assorted relative-time words. */
  211. static TABLE    OtherTable[] = {
  212.     { "tomorrow",    tMINUTE_UNIT,    1 * 24 * 60 },
  213.     { "yesterday",    tMINUTE_UNIT,    -1 * 24 * 60 },
  214.     { "today",        tMINUTE_UNIT,    0 },
  215.     { "now",        tMINUTE_UNIT,    0 },
  216.     { "last",        tUNUMBER,    -1 },
  217.     { "this",        tMINUTE_UNIT,    0 },
  218.     { "next",        tUNUMBER,    2 },
  219.     { "first",        tUNUMBER,    1 },
  220. /*  { "second",        tUNUMBER,    2 }, */
  221.     { "third",        tUNUMBER,    3 },
  222.     { "fourth",        tUNUMBER,    4 },
  223.     { "fifth",        tUNUMBER,    5 },
  224.     { "sixth",        tUNUMBER,    6 },
  225.     { "seventh",    tUNUMBER,    7 },
  226.     { "eighth",        tUNUMBER,    8 },
  227.     { "ninth",        tUNUMBER,    9 },
  228.     { "tenth",        tUNUMBER,    10 },
  229.     { "eleventh",    tUNUMBER,    11 },
  230.     { "twelfth",    tUNUMBER,    12 },
  231.     { "ago",        tAGO,    1 },
  232.     { NULL }
  233. };
  234.  
  235. /* The timezone table. */
  236. static TABLE    TimezoneTable[] = {
  237.     { "gmt",    tZONE,     HOUR( 0) },    /* Greenwich Mean */
  238.     { "ut",    tZONE,     HOUR( 0) },    /* Universal (Coordinated) */
  239.     { "utc",    tZONE,     HOUR( 0) },
  240.     { "wet",    tZONE,     HOUR( 0) },    /* Western European */
  241.     { "bst",    tDAYZONE,  HOUR( 0) },    /* British Summer */
  242.     { "wat",    tZONE,     HOUR( 1) },    /* West Africa */
  243.     { "at",    tZONE,     HOUR( 2) },    /* Azores */
  244. #if    0
  245.     /* For completeness.  BST is also British Summer, and GST is
  246.      * also Guam Standard. */
  247.     { "bst",    tZONE,     HOUR( 3) },    /* Brazil Standard */
  248.     { "gst",    tZONE,     HOUR( 3) },    /* Greenland Standard */
  249. #endif
  250.     { "nft",    tZONE,     HOUR(3.5) },    /* Newfoundland */
  251.     { "nst",    tZONE,     HOUR(3.5) },    /* Newfoundland Standard */
  252.     { "ndt",    tDAYZONE,  HOUR(3.5) },    /* Newfoundland Daylight */
  253.     { "ast",    tZONE,     HOUR( 4) },    /* Atlantic Standard */
  254.     { "adt",    tDAYZONE,  HOUR( 4) },    /* Atlantic Daylight */
  255.     { "est",    tZONE,     HOUR( 5) },    /* Eastern Standard */
  256.     { "edt",    tDAYZONE,  HOUR( 5) },    /* Eastern Daylight */
  257.     { "cst",    tZONE,     HOUR( 6) },    /* Central Standard */
  258.     { "cdt",    tDAYZONE,  HOUR( 6) },    /* Central Daylight */
  259.     { "mst",    tZONE,     HOUR( 7) },    /* Mountain Standard */
  260.     { "mdt",    tDAYZONE,  HOUR( 7) },    /* Mountain Daylight */
  261.     { "pst",    tZONE,     HOUR( 8) },    /* Pacific Standard */
  262.     { "pdt",    tDAYZONE,  HOUR( 8) },    /* Pacific Daylight */
  263.     { "yst",    tZONE,     HOUR( 9) },    /* Yukon Standard */
  264.     { "ydt",    tDAYZONE,  HOUR( 9) },    /* Yukon Daylight */
  265.     { "hst",    tZONE,     HOUR(10) },    /* Hawaii Standard */
  266.     { "hdt",    tDAYZONE,  HOUR(10) },    /* Hawaii Daylight */
  267.     { "cat",    tZONE,     HOUR(10) },    /* Central Alaska */
  268.     { "ahst",    tZONE,     HOUR(10) },    /* Alaska-Hawaii Standard */
  269.     { "nt",    tZONE,     HOUR(11) },    /* Nome */
  270.     { "idlw",    tZONE,     HOUR(12) },    /* International Date Line West */
  271.     { "cet",    tZONE,     -HOUR(1) },    /* Central European */
  272.     { "met",    tZONE,     -HOUR(1) },    /* Middle European */
  273.     { "mewt",    tZONE,     -HOUR(1) },    /* Middle European Winter */
  274.     { "mest",    tDAYZONE,  -HOUR(1) },    /* Middle European Summer */
  275.     { "swt",    tZONE,     -HOUR(1) },    /* Swedish Winter */
  276.     { "sst",    tDAYZONE,  -HOUR(1) },    /* Swedish Summer */
  277.     { "fwt",    tZONE,     -HOUR(1) },    /* French Winter */
  278.     { "fst",    tDAYZONE,  -HOUR(1) },    /* French Summer */
  279.     { "eet",    tZONE,     -HOUR(2) },    /* Eastern Europe, USSR Zone 1 */
  280.     { "bt",    tZONE,     -HOUR(3) },    /* Baghdad, USSR Zone 2 */
  281.     { "it",    tZONE,     -HOUR(3.5) },/* Iran */
  282.     { "zp4",    tZONE,     -HOUR(4) },    /* USSR Zone 3 */
  283.     { "zp5",    tZONE,     -HOUR(5) },    /* USSR Zone 4 */
  284.     { "ist",    tZONE,     -HOUR(5.5) },/* Indian Standard */
  285.     { "zp6",    tZONE,     -HOUR(6) },    /* USSR Zone 5 */
  286. #if    0
  287.     /* For completeness.  NST is also Newfoundland Stanard, nad SST is
  288.      * also Swedish Summer. */
  289.     { "nst",    tZONE,     -HOUR(6.5) },/* North Sumatra */
  290.     { "sst",    tZONE,     -HOUR(7) },    /* South Sumatra, USSR Zone 6 */
  291. #endif    /* 0 */
  292.     { "wast",    tZONE,     -HOUR(7) },    /* West Australian Standard */
  293.     { "wadt",    tDAYZONE,  -HOUR(7) },    /* West Australian Daylight */
  294.     { "jt",    tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
  295.     { "cct",    tZONE,     -HOUR(8) },    /* China Coast, USSR Zone 7 */
  296.     { "jst",    tZONE,     -HOUR(9) },    /* Japan Standard, USSR Zone 8 */
  297.     { "cast",    tZONE,     -HOUR(9.5) },/* Central Australian Standard */
  298.     { "cadt",    tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
  299.     { "east",    tZONE,     -HOUR(10) },    /* Eastern Australian Standard */
  300.     { "eadt",    tDAYZONE,  -HOUR(10) },    /* Eastern Australian Daylight */
  301.     { "gst",    tZONE,     -HOUR(10) },    /* Guam Standard, USSR Zone 9 */
  302.     { "nzt",    tZONE,     -HOUR(12) },    /* New Zealand */
  303.     { "nzst",    tZONE,     -HOUR(12) },    /* New Zealand Standard */
  304.     { "nzdt",    tDAYZONE,  -HOUR(12) },    /* New Zealand Daylight */
  305.     { "idle",    tZONE,     -HOUR(12) },    /* International Date Line East */
  306.     {  NULL  }
  307. };
  308.  
  309. /* Military timezone table. */
  310. static TABLE    MilitaryTable[] = {
  311.     { "a",    tZONE,    HOUR(  1) },
  312.     { "b",    tZONE,    HOUR(  2) },
  313.     { "c",    tZONE,    HOUR(  3) },
  314.     { "d",    tZONE,    HOUR(  4) },
  315.     { "e",    tZONE,    HOUR(  5) },
  316.     { "f",    tZONE,    HOUR(  6) },
  317.     { "g",    tZONE,    HOUR(  7) },
  318.     { "h",    tZONE,    HOUR(  8) },
  319.     { "i",    tZONE,    HOUR(  9) },
  320.     { "k",    tZONE,    HOUR( 10) },
  321.     { "l",    tZONE,    HOUR( 11) },
  322.     { "m",    tZONE,    HOUR( 12) },
  323.     { "n",    tZONE,    HOUR(- 1) },
  324.     { "o",    tZONE,    HOUR(- 2) },
  325.     { "p",    tZONE,    HOUR(- 3) },
  326.     { "q",    tZONE,    HOUR(- 4) },
  327.     { "r",    tZONE,    HOUR(- 5) },
  328.     { "s",    tZONE,    HOUR(- 6) },
  329.     { "t",    tZONE,    HOUR(- 7) },
  330.     { "u",    tZONE,    HOUR(- 8) },
  331.     { "v",    tZONE,    HOUR(- 9) },
  332.     { "w",    tZONE,    HOUR(-10) },
  333.     { "x",    tZONE,    HOUR(-11) },
  334.     { "y",    tZONE,    HOUR(-12) },
  335.     { "z",    tZONE,    HOUR(  0) },
  336.     { NULL }
  337. };
  338.  
  339.  
  340.  
  341.  
  342. /* ARGSUSED */
  343. int
  344. yyerror(s)
  345.     char    *s;
  346. {
  347.   return 0;
  348. }
  349.  
  350.  
  351. static time_t
  352. ToSeconds(Hours, Minutes, Seconds, Meridian)
  353.     time_t    Hours;
  354.     time_t    Minutes;
  355.     time_t    Seconds;
  356.     MERIDIAN    Meridian;
  357. {
  358.     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
  359.     return -1;
  360.     switch (Meridian) {
  361.     case MER24:
  362.     if (Hours < 0 || Hours > 23)
  363.         return -1;
  364.     return (Hours * 60L + Minutes) * 60L + Seconds;
  365.     case MERam:
  366.     if (Hours < 1 || Hours > 12)
  367.         return -1;
  368.     return (Hours * 60L + Minutes) * 60L + Seconds;
  369.     case MERpm:
  370.     if (Hours < 1 || Hours > 12)
  371.         return -1;
  372.     return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
  373.     }
  374.     /* NOTREACHED */
  375. }
  376.  
  377.  
  378. static time_t
  379. Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
  380.     time_t    Month;
  381.     time_t    Day;
  382.     time_t    Year;
  383.     time_t    Hours;
  384.     time_t    Minutes;
  385.     time_t    Seconds;
  386.     MERIDIAN    Meridian;
  387.     DSTMODE    DSTmode;
  388. {
  389.     static int    DaysInMonth[12] = {
  390.     31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  391.     };
  392.     time_t    tod;
  393.     time_t    Julian;
  394.     int        i;
  395.  
  396.     if (Year < 0)
  397.     Year = -Year;
  398.     if (Year < 100)
  399.     Year += 1900;
  400.     DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
  401.             ? 29 : 28;
  402.     if (Year < EPOCH || Year > 1999
  403.      || Month < 1 || Month > 12
  404.      /* Lint fluff:  "conversion from long may lose accuracy" */
  405.      || Day < 1 || Day > DaysInMonth[(int)--Month])
  406.     return -1;
  407.  
  408.     for (Julian = Day - 1, i = 0; i < Month; i++)
  409.     Julian += DaysInMonth[i];
  410.     for (i = EPOCH; i < Year; i++)
  411.     Julian += 365 + (i % 4 == 0);
  412.     Julian *= SECSPERDAY;
  413.     Julian += yyTimezone * 60L;
  414.     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
  415.     return -1;
  416.     Julian += tod;
  417.     if (DSTmode == DSTon
  418.      || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
  419.     Julian -= 60 * 60;
  420.     return Julian;
  421. }
  422.  
  423.  
  424. static time_t
  425. DSTcorrect(Start, Future)
  426.     time_t    Start;
  427.     time_t    Future;
  428. {
  429.     time_t    StartDay;
  430.     time_t    FutureDay;
  431.  
  432.     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
  433.     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
  434.     return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
  435. }
  436.  
  437.  
  438. static time_t
  439. RelativeDate(Start, DayOrdinal, DayNumber)
  440.     time_t    Start;
  441.     time_t    DayOrdinal;
  442.     time_t    DayNumber;
  443. {
  444.     struct tm    *tm;
  445.     time_t    now;
  446.  
  447.     now = Start;
  448.     tm = localtime(&now);
  449.     now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
  450.     now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
  451.     return DSTcorrect(Start, now);
  452. }
  453.  
  454.  
  455. static time_t
  456. RelativeMonth(Start, RelMonth)
  457.     time_t    Start;
  458.     time_t    RelMonth;
  459. {
  460.     struct tm    *tm;
  461.     time_t    Month;
  462.     time_t    Year;
  463.  
  464.     if (RelMonth == 0)
  465.     return 0;
  466.     tm = localtime(&Start);
  467.     Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
  468.     Year = Month / 12;
  469.     Month = Month % 12 + 1;
  470.     return DSTcorrect(Start,
  471.         Convert(Month, (time_t)tm->tm_mday, Year,
  472.         (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
  473.         MER24, DSTmaybe));
  474. }
  475.  
  476.  
  477. static int
  478. LookupWord(buff)
  479.     char        *buff;
  480. {
  481.     register char    *p;
  482.     register char    *q;
  483.     register TABLE    *tp;
  484.     int            i;
  485.     int            abbrev;
  486.  
  487.     /* Make it lowercase. */
  488.     for (p = buff; *p; p++)
  489.     if (isupper(*p))
  490.         *p = tolower(*p);
  491.  
  492.     if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
  493.     yylval.Meridian = MERam;
  494.     return tMERIDIAN;
  495.     }
  496.     if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
  497.     yylval.Meridian = MERpm;
  498.     return tMERIDIAN;
  499.     }
  500.  
  501.     /* See if we have an abbreviation for a month. */
  502.     if (strlen(buff) == 3)
  503.     abbrev = 1;
  504.     else if (strlen(buff) == 4 && buff[3] == '.') {
  505.     abbrev = 1;
  506.     buff[3] = '\0';
  507.     }
  508.     else
  509.     abbrev = 0;
  510.  
  511.     for (tp = MonthDayTable; tp->name; tp++) {
  512.     if (abbrev) {
  513.         if (strncmp(buff, tp->name, 3) == 0) {
  514.         yylval.Number = tp->value;
  515.         return tp->type;
  516.         }
  517.     }
  518.     else if (strcmp(buff, tp->name) == 0) {
  519.         yylval.Number = tp->value;
  520.         return tp->type;
  521.     }
  522.     }
  523.  
  524.     for (tp = TimezoneTable; tp->name; tp++)
  525.     if (strcmp(buff, tp->name) == 0) {
  526.         yylval.Number = tp->value;
  527.         return tp->type;
  528.     }
  529.  
  530.     for (tp = UnitsTable; tp->name; tp++)
  531.     if (strcmp(buff, tp->name) == 0) {
  532.         yylval.Number = tp->value;
  533.         return tp->type;
  534.     }
  535.  
  536.     /* Strip off any plural and try the units table again. */
  537.     i = strlen(buff) - 1;
  538.     if (buff[i] == 's') {
  539.     buff[i] = '\0';
  540.     for (tp = UnitsTable; tp->name; tp++)
  541.         if (strcmp(buff, tp->name) == 0) {
  542.         yylval.Number = tp->value;
  543.         return tp->type;
  544.         }
  545.     buff[i] = 's';        /* Put back for "this" in OtherTable. */
  546.     }
  547.  
  548.     for (tp = OtherTable; tp->name; tp++)
  549.     if (strcmp(buff, tp->name) == 0) {
  550.         yylval.Number = tp->value;
  551.         return tp->type;
  552.     }
  553.  
  554.     /* Military timezones. */
  555.     if (buff[1] == '\0' && isalpha(*buff)) {
  556.     for (tp = MilitaryTable; tp->name; tp++)
  557.         if (strcmp(buff, tp->name) == 0) {
  558.         yylval.Number = tp->value;
  559.         return tp->type;
  560.         }
  561.     }
  562.  
  563.     /* Drop out any periods and try the timezone table again. */
  564.     for (i = 0, p = q = buff; *q; q++)
  565.     if (*q != '.')
  566.         *p++ = *q;
  567.     else
  568.         i++;
  569.     *p = '\0';
  570.     if (i)
  571.     for (tp = TimezoneTable; tp->name; tp++)
  572.         if (strcmp(buff, tp->name) == 0) {
  573.         yylval.Number = tp->value;
  574.         return tp->type;
  575.         }
  576.  
  577.     return tID;
  578. }
  579.  
  580.  
  581. int
  582. yylex()
  583. {
  584.     register char    c;
  585.     register char    *p;
  586.     char        buff[20];
  587.     int            Count;
  588.     int            sign;
  589.  
  590.     for ( ; ; ) {
  591.     while (isspace(*yyInput))
  592.         yyInput++;
  593.  
  594.     if (isdigit(c = *yyInput) || c == '-' || c == '+') {
  595.         if (c == '-' || c == '+') {
  596.         sign = c == '-' ? -1 : 1;
  597.         if (!isdigit(*++yyInput))
  598.             /* skip the '-' sign */
  599.             continue;
  600.         }
  601.         else
  602.         sign = 0;
  603.         for (yylval.Number = 0; isdigit(c = *yyInput++); )
  604.         yylval.Number = 10 * yylval.Number + c - '0';
  605.         yyInput--;
  606.         if (sign < 0)
  607.         yylval.Number = -yylval.Number;
  608.         return sign ? tSNUMBER : tUNUMBER;
  609.     }
  610.     if (isalpha(c)) {
  611.         for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
  612.         if (p < &buff[sizeof buff - 1])
  613.             *p++ = c;
  614.         *p = '\0';
  615.         yyInput--;
  616.         return LookupWord(buff);
  617.     }
  618.     if (c != '(')
  619.         return *yyInput++;
  620.     Count = 0;
  621.     do {
  622.         c = *yyInput++;
  623.         if (c == '\0')
  624.         return c;
  625.         if (c == '(')
  626.         Count++;
  627.         else if (c == ')')
  628.         Count--;
  629.     } while (Count > 0);
  630.     }
  631. }
  632.  
  633.  
  634. time_t
  635. get_date(p, now)
  636.     char        *p;
  637.     struct timeb    *now;
  638. {
  639.     struct tm        *tm;
  640.     struct timeb    ftz;
  641.     time_t        Start;
  642.     time_t        tod;
  643.  
  644.     yyInput = p;
  645.     if (now == NULL) {
  646.     now = &ftz;
  647. #if    defined(NEED_TZSET)
  648.     (void)time(&ftz.time);
  649.     /* Set the timezone global. */
  650.     tzset();
  651.     ftz.timezone = (int) timezone / 60;
  652. #else
  653.     (void)ftime(&ftz);
  654. #endif    /* defined(NEED_TZSET) */
  655.     }
  656.  
  657.     tm = localtime(&now->time);
  658.     yyYear = tm->tm_year;
  659.     yyMonth = tm->tm_mon + 1;
  660.     yyDay = tm->tm_mday;
  661.     yyTimezone = now->timezone;
  662.     yyDSTmode = DSTmaybe;
  663.     yyHour = 0;
  664.     yyMinutes = 0;
  665.     yySeconds = 0;
  666.     yyMeridian = MER24;
  667.     yyRelSeconds = 0;
  668.     yyRelMonth = 0;
  669.     yyHaveDate = 0;
  670.     yyHaveDay = 0;
  671.     yyHaveRel = 0;
  672.     yyHaveTime = 0;
  673.     yyHaveZone = 0;
  674.  
  675.     if (yyparse()
  676.      || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
  677.     return -1;
  678.  
  679.     if (yyHaveDate || yyHaveTime || yyHaveDay) {
  680.     Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
  681.             yyMeridian, yyDSTmode);
  682.     if (Start < 0)
  683.         return -1;
  684.     }
  685.     else {
  686.     Start = now->time;
  687.     if (!yyHaveRel)
  688.         Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
  689.     }
  690.  
  691.     Start += yyRelSeconds;
  692.     Start += RelativeMonth(Start, yyRelMonth);
  693.  
  694.     if (yyHaveDay && !yyHaveDate) {
  695.     tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
  696.     Start += tod;
  697.     }
  698.  
  699.     /* Have to do *something* with a legitimate -1 so it's distinguishable
  700.      * from the error return value.  (Alternately could set errno on error.) */
  701.     return Start == -1 ? 0 : Start;
  702. }
  703.  
  704.  
  705. #if    defined(TEST)
  706.  
  707. /* ARGSUSED */
  708. main(ac, av)
  709.     int        ac;
  710.     char    *av[];
  711. {
  712.     char    buff[128];
  713.     time_t    d;
  714.  
  715.     (void)printf("Enter date, or blank line to exit.\n\t> ");
  716.     (void)fflush(stdout);
  717.     while (gets(buff) && buff[0]) {
  718.     d = get_date(buff, (struct timeb *)NULL);
  719.     if (d == -1)
  720.         (void)printf("Bad format - couldn't convert.\n");
  721.     else
  722.         (void)printf("%s", ctime(&d));
  723.     (void)printf("\t> ");
  724.     (void)fflush(stdout);
  725.     }
  726.     exit(0);
  727.     /* NOTREACHED */
  728. }
  729. #endif    /* defined(TEST) */
  730. yytabelem yyexca[] ={
  731. -1, 1,
  732.     0, -1,
  733.     -2, 0,
  734.     };
  735. # define YYNPROD 39
  736. # define YYLAST 221
  737. yytabelem yyact[]={
  738.  
  739.     13,    11,    22,    39,    16,    12,    18,    17,    15,     9,
  740.     10,    40,    44,    20,    43,    42,    46,    29,    35,    34,
  741.     33,    30,    27,    32,    31,    41,    36,    28,    37,    14,
  742.      8,     7,     6,     5,     4,     3,     2,     1,     0,     0,
  743.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  744.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  745.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  746.      0,     0,    45,     0,     0,     0,     0,     0,     0,     0,
  747.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  748.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  749.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  750.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  751.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  752.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  753.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  754.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  755.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  756.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  757.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  758.      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
  759.      0,     0,     0,     0,     0,     0,    40,     0,     0,     0,
  760.      0,    38,     0,    21,     0,     0,    19,    24,    23,    26,
  761.     25 };
  762. yytabelem yypact[]={
  763.  
  764.  -1000,  -258, -1000, -1000, -1000, -1000, -1000, -1000, -1000,   -45,
  765.  -1000, -1000,  -245,   -17,  -240,  -241, -1000, -1000, -1000, -1000,
  766.   -247, -1000,  -248,  -249, -1000, -1000, -1000,   -18, -1000, -1000,
  767.  -1000, -1000, -1000,   -55,   -22, -1000,  -252, -1000, -1000,  -253,
  768.  -1000,  -255, -1000,  -250, -1000, -1000, -1000 };
  769. yytabelem yypgo[]={
  770.  
  771.      0,    28,    37,    36,    35,    34,    33,    32,    31,    30,
  772.     29 };
  773. yytabelem yyr1[]={
  774.  
  775.      0,     2,     2,     3,     3,     3,     3,     3,     3,     4,
  776.      4,     4,     4,     4,     5,     5,     7,     7,     7,     6,
  777.      6,     6,     6,     6,     6,     8,     8,    10,    10,    10,
  778.     10,    10,    10,    10,    10,    10,     9,     1,     1 };
  779. yytabelem yyr2[]={
  780.  
  781.      0,     0,     4,     3,     3,     3,     3,     3,     2,     5,
  782.      9,     9,    13,    13,     3,     3,     3,     5,     5,     7,
  783.     11,     5,     9,     5,     7,     5,     2,     5,     5,     3,
  784.      5,     5,     3,     5,     5,     3,     3,     1,     3 };
  785. yytabelem yychk[]={
  786.  
  787.  -1000,    -2,    -3,    -4,    -5,    -6,    -7,    -8,    -9,   267,
  788.    268,   259,   263,   258,   -10,   266,   262,   265,   264,   261,
  789.     58,   258,    47,   263,   262,   265,   264,   267,    44,   257,
  790.    262,   265,   264,   267,   267,   267,    44,    -1,   266,    58,
  791.    261,    47,   267,   267,   267,    -1,   266 };
  792. yytabelem yydef[]={
  793.  
  794.      1,    -2,     2,     3,     4,     5,     6,     7,     8,    36,
  795.     14,    15,     0,    16,    26,     0,    29,    32,    35,     9,
  796.      0,    18,     0,    23,    27,    31,    34,    21,    17,    25,
  797.     28,    30,    33,    37,    19,    24,     0,    10,    11,     0,
  798.     38,     0,    22,    37,    20,    12,    13 };
  799. typedef struct { char *t_name; int t_val; } yytoktype;
  800. #ifndef YYDEBUG
  801. #    define YYDEBUG    0    /* don't allow debugging */
  802. #endif
  803.  
  804. #if YYDEBUG
  805.  
  806. yytoktype yytoks[] =
  807. {
  808.     "tAGO",    257,
  809.     "tDAY",    258,
  810.     "tDAYZONE",    259,
  811.     "tID",    260,
  812.     "tMERIDIAN",    261,
  813.     "tMINUTE_UNIT",    262,
  814.     "tMONTH",    263,
  815.     "tMONTH_UNIT",    264,
  816.     "tSEC_UNIT",    265,
  817.     "tSNUMBER",    266,
  818.     "tUNUMBER",    267,
  819.     "tZONE",    268,
  820.     "-unknown-",    -1    /* ends search */
  821. };
  822.  
  823. char * yyreds[] =
  824. {
  825.     "-no such reduction-",
  826.     "spec : /* empty */",
  827.     "spec : spec item",
  828.     "item : time",
  829.     "item : zone",
  830.     "item : date",
  831.     "item : day",
  832.     "item : rel",
  833.     "item : number",
  834.     "time : tUNUMBER tMERIDIAN",
  835.     "time : tUNUMBER ':' tUNUMBER o_merid",
  836.     "time : tUNUMBER ':' tUNUMBER tSNUMBER",
  837.     "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
  838.     "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER",
  839.     "zone : tZONE",
  840.     "zone : tDAYZONE",
  841.     "day : tDAY",
  842.     "day : tDAY ','",
  843.     "day : tUNUMBER tDAY",
  844.     "date : tUNUMBER '/' tUNUMBER",
  845.     "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
  846.     "date : tMONTH tUNUMBER",
  847.     "date : tMONTH tUNUMBER ',' tUNUMBER",
  848.     "date : tUNUMBER tMONTH",
  849.     "date : tUNUMBER tMONTH tUNUMBER",
  850.     "rel : relunit tAGO",
  851.     "rel : relunit",
  852.     "relunit : tUNUMBER tMINUTE_UNIT",
  853.     "relunit : tSNUMBER tMINUTE_UNIT",
  854.     "relunit : tMINUTE_UNIT",
  855.     "relunit : tSNUMBER tSEC_UNIT",
  856.     "relunit : tUNUMBER tSEC_UNIT",
  857.     "relunit : tSEC_UNIT",
  858.     "relunit : tSNUMBER tMONTH_UNIT",
  859.     "relunit : tUNUMBER tMONTH_UNIT",
  860.     "relunit : tMONTH_UNIT",
  861.     "number : tUNUMBER",
  862.     "o_merid : /* empty */",
  863.     "o_merid : tMERIDIAN",
  864. };
  865. #endif /* YYDEBUG */
  866. #ident    "@(#)yaccpar    2.3 - 88/05/27"
  867.  
  868. /*
  869. ** Skeleton parser driver for yacc output
  870. */
  871.  
  872. /*
  873. ** yacc user known macros and defines
  874. */
  875. #define YYERROR        goto yyerrlab
  876. #define YYACCEPT    return(0)
  877. #define YYABORT        return(1)
  878. #define YYBACKUP( newtoken, newvalue )\
  879. {\
  880.     if ( yychar >= 0 || ( yyr2[ yytmp ] >> 1 ) != 1 )\
  881.     {\
  882.         yyerror( "syntax error - cannot backup" );\
  883.         goto yyerrlab;\
  884.     }\
  885.     yychar = newtoken;\
  886.     yystate = *yyps;\
  887.     yylval = newvalue;\
  888.     goto yynewstate;\
  889. }
  890. #define YYRECOVERING()    (!!yyerrflag)
  891. #ifndef YYDEBUG
  892. #    define YYDEBUG    1    /* make debugging available */
  893. #endif
  894.  
  895. /*
  896. ** user known globals
  897. */
  898. int yydebug;            /* set to 1 to get debugging */
  899.  
  900. /*
  901. ** driver internal defines
  902. */
  903. #define YYFLAG        (-1000)
  904.  
  905. /*
  906. ** global variables used by the parser
  907. */
  908. YYSTYPE yyv[ YYMAXDEPTH ];    /* value stack */
  909. int yys[ YYMAXDEPTH ];        /* state stack */
  910.  
  911. YYSTYPE *yypv;            /* top of value stack */
  912. int *yyps;            /* top of state stack */
  913.  
  914. int yystate;            /* current state */
  915. int yytmp;            /* extra var (lasts between blocks) */
  916.  
  917. int yynerrs;            /* number of errors */
  918. int yyerrflag;            /* error recovery flag */
  919. int yychar;            /* current input token number */
  920.  
  921.  
  922.  
  923. /*
  924. ** yyparse - return 0 if worked, 1 if syntax error not recovered from
  925. */
  926. int
  927. yyparse()
  928. {
  929.     register YYSTYPE *yypvt;    /* top of value stack for $vars */
  930.  
  931.     /*
  932.     ** Initialize externals - yyparse may be called more than once
  933.     */
  934.     yypv = &yyv[-1];
  935.     yyps = &yys[-1];
  936.     yystate = 0;
  937.     yytmp = 0;
  938.     yynerrs = 0;
  939.     yyerrflag = 0;
  940.     yychar = -1;
  941.  
  942.     goto yystack;
  943.     {
  944.         register YYSTYPE *yy_pv;    /* top of value stack */
  945.         register int *yy_ps;        /* top of state stack */
  946.         register int yy_state;        /* current state */
  947.         register int  yy_n;        /* internal state number info */
  948.  
  949.         /*
  950.         ** get globals into registers.
  951.         ** branch to here only if YYBACKUP was called.
  952.         */
  953.     yynewstate:
  954.         yy_pv = yypv;
  955.         yy_ps = yyps;
  956.         yy_state = yystate;
  957.         goto yy_newstate;
  958.  
  959.         /*
  960.         ** get globals into registers.
  961.         ** either we just started, or we just finished a reduction
  962.         */
  963.     yystack:
  964.         yy_pv = yypv;
  965.         yy_ps = yyps;
  966.         yy_state = yystate;
  967.  
  968.         /*
  969.         ** top of for (;;) loop while no reductions done
  970.         */
  971.     yy_stack:
  972.         /*
  973.         ** put a state and value onto the stacks
  974.         */
  975. #if YYDEBUG
  976.         /*
  977.         ** if debugging, look up token value in list of value vs.
  978.         ** name pairs.  0 and negative (-1) are special values.
  979.         ** Note: linear search is used since time is not a real
  980.         ** consideration while debugging.
  981.         */
  982.         if ( yydebug )
  983.         {
  984.             register int yy_i;
  985.  
  986.             printf( "State %d, token ", yy_state );
  987.             if ( yychar == 0 )
  988.                 printf( "end-of-file\n" );
  989.             else if ( yychar < 0 )
  990.                 printf( "-none-\n" );
  991.             else
  992.             {
  993.                 for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
  994.                     yy_i++ )
  995.                 {
  996.                     if ( yytoks[yy_i].t_val == yychar )
  997.                         break;
  998.                 }
  999.                 printf( "%s\n", yytoks[yy_i].t_name );
  1000.             }
  1001.         }
  1002. #endif /* YYDEBUG */
  1003.         if ( ++yy_ps >= &yys[ YYMAXDEPTH ] )    /* room on stack? */
  1004.         {
  1005.             yyerror( "yacc stack overflow" );
  1006.             YYABORT;
  1007.         }
  1008.         *yy_ps = yy_state;
  1009.         *++yy_pv = yyval;
  1010.  
  1011.         /*
  1012.         ** we have a new state - find out what to do
  1013.         */
  1014.     yy_newstate:
  1015.         if ( ( yy_n = yypact[ yy_state ] ) <= YYFLAG )
  1016.             goto yydefault;        /* simple state */
  1017. #if YYDEBUG
  1018.         /*
  1019.         ** if debugging, need to mark whether new token grabbed
  1020.         */
  1021.         yytmp = yychar < 0;
  1022. #endif
  1023.         if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
  1024.             yychar = 0;        /* reached EOF */
  1025. #if YYDEBUG
  1026.         if ( yydebug && yytmp )
  1027.         {
  1028.             register int yy_i;
  1029.  
  1030.             printf( "Received token " );
  1031.             if ( yychar == 0 )
  1032.                 printf( "end-of-file\n" );
  1033.             else if ( yychar < 0 )
  1034.                 printf( "-none-\n" );
  1035.             else
  1036.             {
  1037.                 for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
  1038.                     yy_i++ )
  1039.                 {
  1040.                     if ( yytoks[yy_i].t_val == yychar )
  1041.                         break;
  1042.                 }
  1043.                 printf( "%s\n", yytoks[yy_i].t_name );
  1044.             }
  1045.         }
  1046. #endif /* YYDEBUG */
  1047.         if ( ( ( yy_n += yychar ) < 0 ) || ( yy_n >= YYLAST ) )
  1048.             goto yydefault;
  1049.         if ( yychk[ yy_n = yyact[ yy_n ] ] == yychar )    /*valid shift*/
  1050.         {
  1051.             yychar = -1;
  1052.             yyval = yylval;
  1053.             yy_state = yy_n;
  1054.             if ( yyerrflag > 0 )
  1055.                 yyerrflag--;
  1056.             goto yy_stack;
  1057.         }
  1058.  
  1059.     yydefault:
  1060.         if ( ( yy_n = yydef[ yy_state ] ) == -2 )
  1061.         {
  1062. #if YYDEBUG
  1063.             yytmp = yychar < 0;
  1064. #endif
  1065.             if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
  1066.                 yychar = 0;        /* reached EOF */
  1067. #if YYDEBUG
  1068.             if ( yydebug && yytmp )
  1069.             {
  1070.                 register int yy_i;
  1071.  
  1072.                 printf( "Received token " );
  1073.                 if ( yychar == 0 )
  1074.                     printf( "end-of-file\n" );
  1075.                 else if ( yychar < 0 )
  1076.                     printf( "-none-\n" );
  1077.                 else
  1078.                 {
  1079.                     for ( yy_i = 0;
  1080.                         yytoks[yy_i].t_val >= 0;
  1081.                         yy_i++ )
  1082.                     {
  1083.                         if ( yytoks[yy_i].t_val
  1084.                             == yychar )
  1085.                         {
  1086.                             break;
  1087.                         }
  1088.                     }
  1089.                     printf( "%s\n", yytoks[yy_i].t_name );
  1090.                 }
  1091.             }
  1092. #endif /* YYDEBUG */
  1093.             /*
  1094.             ** look through exception table
  1095.             */
  1096.             {
  1097.                 register int *yyxi = yyexca;
  1098.  
  1099.                 while ( ( *yyxi != -1 ) ||
  1100.                     ( yyxi[1] != yy_state ) )
  1101.                 {
  1102.                     yyxi += 2;
  1103.                 }
  1104.                 while ( ( *(yyxi += 2) >= 0 ) &&
  1105.                     ( *yyxi != yychar ) )
  1106.                     ;
  1107.                 if ( ( yy_n = yyxi[1] ) < 0 )
  1108.                     YYACCEPT;
  1109.             }
  1110.         }
  1111.  
  1112.         /*
  1113.         ** check for syntax error
  1114.         */
  1115.         if ( yy_n == 0 )    /* have an error */
  1116.         {
  1117.             /* no worry about speed here! */
  1118.             switch ( yyerrflag )
  1119.             {
  1120.             case 0:        /* new error */
  1121.                 yyerror( "syntax error" );
  1122.                 goto skip_init;
  1123.             yyerrlab:
  1124.                 /*
  1125.                 ** get globals into registers.
  1126.                 ** we have a user generated syntax type error
  1127.                 */
  1128.                 yy_pv = yypv;
  1129.                 yy_ps = yyps;
  1130.                 yy_state = yystate;
  1131.                 yynerrs++;
  1132.             skip_init:
  1133.             case 1:
  1134.             case 2:        /* incompletely recovered error */
  1135.                     /* try again... */
  1136.                 yyerrflag = 3;
  1137.                 /*
  1138.                 ** find state where "error" is a legal
  1139.                 ** shift action
  1140.                 */
  1141.                 while ( yy_ps >= yys )
  1142.                 {
  1143.                     yy_n = yypact[ *yy_ps ] + YYERRCODE;
  1144.                     if ( yy_n >= 0 && yy_n < YYLAST &&
  1145.                         yychk[yyact[yy_n]] == YYERRCODE)                    {
  1146.                         /*
  1147.                         ** simulate shift of "error"
  1148.                         */
  1149.                         yy_state = yyact[ yy_n ];
  1150.                         goto yy_stack;
  1151.                     }
  1152.                     /*
  1153.                     ** current state has no shift on
  1154.                     ** "error", pop stack
  1155.                     */
  1156. #if YYDEBUG
  1157. #    define _POP_ "Error recovery pops state %d, uncovers state %d\n"
  1158.                     if ( yydebug )
  1159.                         printf( _POP_, *yy_ps,
  1160.                             yy_ps[-1] );
  1161. #    undef _POP_
  1162. #endif
  1163.                     yy_ps--;
  1164.                     yy_pv--;
  1165.                 }
  1166.                 /*
  1167.                 ** there is no state on stack with "error" as
  1168.                 ** a valid shift.  give up.
  1169.                 */
  1170.                 YYABORT;
  1171.             case 3:        /* no shift yet; eat a token */
  1172. #if YYDEBUG
  1173.                 /*
  1174.                 ** if debugging, look up token in list of
  1175.                 ** pairs.  0 and negative shouldn't occur,
  1176.                 ** but since timing doesn't matter when
  1177.                 ** debugging, it doesn't hurt to leave the
  1178.                 ** tests here.
  1179.                 */
  1180.                 if ( yydebug )
  1181.                 {
  1182.                     register int yy_i;
  1183.  
  1184.                     printf( "Error recovery discards " );
  1185.                     if ( yychar == 0 )
  1186.                         printf( "token end-of-file\n" );
  1187.                     else if ( yychar < 0 )
  1188.                         printf( "token -none-\n" );
  1189.                     else
  1190.                     {
  1191.                         for ( yy_i = 0;
  1192.                             yytoks[yy_i].t_val >= 0;
  1193.                             yy_i++ )
  1194.                         {
  1195.                             if ( yytoks[yy_i].t_val
  1196.                                 == yychar )
  1197.                             {
  1198.                                 break;
  1199.                             }
  1200.                         }
  1201.                         printf( "token %s\n",
  1202.                             yytoks[yy_i].t_name );
  1203.                     }
  1204.                 }
  1205. #endif /* YYDEBUG */
  1206.                 if ( yychar == 0 )    /* reached EOF. quit */
  1207.                     YYABORT;
  1208.                 yychar = -1;
  1209.                 goto yy_newstate;
  1210.             }
  1211.         }/* end if ( yy_n == 0 ) */
  1212.         /*
  1213.         ** reduction by production yy_n
  1214.         ** put stack tops, etc. so things right after switch
  1215.         */
  1216. #if YYDEBUG
  1217.         /*
  1218.         ** if debugging, print the string that is the user's
  1219.         ** specification of the reduction which is just about
  1220.         ** to be done.
  1221.         */
  1222.         if ( yydebug )
  1223.             printf( "Reduce by (%d) \"%s\"\n",
  1224.                 yy_n, yyreds[ yy_n ] );
  1225. #endif
  1226.         yytmp = yy_n;            /* value to switch over */
  1227.         yypvt = yy_pv;            /* $vars top of value stack */
  1228.         /*
  1229.         ** Look in goto table for next state
  1230.         ** Sorry about using yy_state here as temporary
  1231.         ** register variable, but why not, if it works...
  1232.         ** If yyr2[ yy_n ] doesn't have the low order bit
  1233.         ** set, then there is no action to be done for
  1234.         ** this reduction.  So, no saving & unsaving of
  1235.         ** registers done.  The only difference between the
  1236.         ** code just after the if and the body of the if is
  1237.         ** the goto yy_stack in the body.  This way the test
  1238.         ** can be made before the choice of what to do is needed.
  1239.         */
  1240.         {
  1241.             /* length of production doubled with extra bit */
  1242.             register int yy_len = yyr2[ yy_n ];
  1243.  
  1244.             if ( !( yy_len & 01 ) )
  1245.             {
  1246.                 yy_len >>= 1;
  1247.                 yyval = ( yy_pv -= yy_len )[1];    /* $$ = $1 */
  1248.                 yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
  1249.                     *( yy_ps -= yy_len ) + 1;
  1250.                 if ( yy_state >= YYLAST ||
  1251.                     yychk[ yy_state =
  1252.                     yyact[ yy_state ] ] != -yy_n )
  1253.                 {
  1254.                     yy_state = yyact[ yypgo[ yy_n ] ];
  1255.                 }
  1256.                 goto yy_stack;
  1257.             }
  1258.             yy_len >>= 1;
  1259.             yyval = ( yy_pv -= yy_len )[1];    /* $$ = $1 */
  1260.             yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
  1261.                 *( yy_ps -= yy_len ) + 1;
  1262.             if ( yy_state >= YYLAST ||
  1263.                 yychk[ yy_state = yyact[ yy_state ] ] != -yy_n )
  1264.             {
  1265.                 yy_state = yyact[ yypgo[ yy_n ] ];
  1266.             }
  1267.         }
  1268.                     /* save until reenter driver code */
  1269.         yystate = yy_state;
  1270.         yyps = yy_ps;
  1271.         yypv = yy_pv;
  1272.     }
  1273.     /*
  1274.     ** code supplied by user is placed in this switch
  1275.     */
  1276.     switch( yytmp )
  1277.     {
  1278.         
  1279. case 3:
  1280. # line 153 "getdate.y"
  1281. {
  1282.         yyHaveTime++;
  1283.     } break;
  1284. case 4:
  1285. # line 156 "getdate.y"
  1286. {
  1287.         yyHaveZone++;
  1288.     } break;
  1289. case 5:
  1290. # line 159 "getdate.y"
  1291. {
  1292.         yyHaveDate++;
  1293.     } break;
  1294. case 6:
  1295. # line 162 "getdate.y"
  1296. {
  1297.         yyHaveDay++;
  1298.     } break;
  1299. case 7:
  1300. # line 165 "getdate.y"
  1301. {
  1302.         yyHaveRel++;
  1303.     } break;
  1304. case 9:
  1305. # line 171 "getdate.y"
  1306. {
  1307.         yyHour = yypvt[-1].Number;
  1308.         yyMinutes = 0;
  1309.         yySeconds = 0;
  1310.         yyMeridian = yypvt[-0].Meridian;
  1311.     } break;
  1312. case 10:
  1313. # line 177 "getdate.y"
  1314. {
  1315.         yyHour = yypvt[-3].Number;
  1316.         yyMinutes = yypvt[-1].Number;
  1317.         yySeconds = 0;
  1318.         yyMeridian = yypvt[-0].Meridian;
  1319.     } break;
  1320. case 11:
  1321. # line 183 "getdate.y"
  1322. {
  1323.         yyHour = yypvt[-3].Number;
  1324.         yyMinutes = yypvt[-1].Number;
  1325.         yyMeridian = MER24;
  1326.         yyDSTmode = DSToff;
  1327.         yyTimezone = - (yypvt[-0].Number % 100 + (yypvt[-0].Number / 100) * 60);
  1328.     } break;
  1329. case 12:
  1330. # line 190 "getdate.y"
  1331. {
  1332.         yyHour = yypvt[-5].Number;
  1333.         yyMinutes = yypvt[-3].Number;
  1334.         yySeconds = yypvt[-1].Number;
  1335.         yyMeridian = yypvt[-0].Meridian;
  1336.     } break;
  1337. case 13:
  1338. # line 196 "getdate.y"
  1339. {
  1340.         yyHour = yypvt[-5].Number;
  1341.         yyMinutes = yypvt[-3].Number;
  1342.         yySeconds = yypvt[-1].Number;
  1343.         yyMeridian = MER24;
  1344.         yyDSTmode = DSToff;
  1345.         yyTimezone = - (yypvt[-0].Number % 100 + (yypvt[-0].Number / 100) * 60);
  1346.     } break;
  1347. case 14:
  1348. # line 206 "getdate.y"
  1349. {
  1350.         yyTimezone = yypvt[-0].Number;
  1351.         yyDSTmode = DSToff;
  1352.     } break;
  1353. case 15:
  1354. # line 210 "getdate.y"
  1355. {
  1356.         yyTimezone = yypvt[-0].Number;
  1357.         yyDSTmode = DSTon;
  1358.     } break;
  1359. case 16:
  1360. # line 216 "getdate.y"
  1361. {
  1362.         yyDayOrdinal = 1;
  1363.         yyDayNumber = yypvt[-0].Number;
  1364.     } break;
  1365. case 17:
  1366. # line 220 "getdate.y"
  1367. {
  1368.         yyDayOrdinal = 1;
  1369.         yyDayNumber = yypvt[-1].Number;
  1370.     } break;
  1371. case 18:
  1372. # line 224 "getdate.y"
  1373. {
  1374.         yyDayOrdinal = yypvt[-1].Number;
  1375.         yyDayNumber = yypvt[-0].Number;
  1376.     } break;
  1377. case 19:
  1378. # line 230 "getdate.y"
  1379. {
  1380.         yyMonth = yypvt[-2].Number;
  1381.         yyDay = yypvt[-0].Number;
  1382.     } break;
  1383. case 20:
  1384. # line 234 "getdate.y"
  1385. {
  1386.         yyMonth = yypvt[-4].Number;
  1387.         yyDay = yypvt[-2].Number;
  1388.         yyYear = yypvt[-0].Number;
  1389.     } break;
  1390. case 21:
  1391. # line 239 "getdate.y"
  1392. {
  1393.         yyMonth = yypvt[-1].Number;
  1394.         yyDay = yypvt[-0].Number;
  1395.     } break;
  1396. case 22:
  1397. # line 243 "getdate.y"
  1398. {
  1399.         yyMonth = yypvt[-3].Number;
  1400.         yyDay = yypvt[-2].Number;
  1401.         yyYear = yypvt[-0].Number;
  1402.     } break;
  1403. case 23:
  1404. # line 248 "getdate.y"
  1405. {
  1406.         yyMonth = yypvt[-0].Number;
  1407.         yyDay = yypvt[-1].Number;
  1408.     } break;
  1409. case 24:
  1410. # line 252 "getdate.y"
  1411. {
  1412.         yyMonth = yypvt[-1].Number;
  1413.         yyDay = yypvt[-2].Number;
  1414.         yyYear = yypvt[-0].Number;
  1415.     } break;
  1416. case 25:
  1417. # line 259 "getdate.y"
  1418. {
  1419.         yyRelSeconds = -yyRelSeconds;
  1420.         yyRelMonth = -yyRelMonth;
  1421.     } break;
  1422. case 27:
  1423. # line 266 "getdate.y"
  1424. {
  1425.         yyRelSeconds += yypvt[-1].Number * yypvt[-0].Number * 60L;
  1426.     } break;
  1427. case 28:
  1428. # line 269 "getdate.y"
  1429. {
  1430.         yyRelSeconds += yypvt[-1].Number * yypvt[-0].Number * 60L;
  1431.     } break;
  1432. case 29:
  1433. # line 272 "getdate.y"
  1434. {
  1435.         yyRelSeconds += yypvt[-0].Number * 60L;
  1436.     } break;
  1437. case 30:
  1438. # line 275 "getdate.y"
  1439. {
  1440.         yyRelSeconds += yypvt[-1].Number;
  1441.     } break;
  1442. case 31:
  1443. # line 278 "getdate.y"
  1444. {
  1445.         yyRelSeconds += yypvt[-1].Number;
  1446.     } break;
  1447. case 32:
  1448. # line 281 "getdate.y"
  1449. {
  1450.         yyRelSeconds++;
  1451.     } break;
  1452. case 33:
  1453. # line 284 "getdate.y"
  1454. {
  1455.         yyRelMonth += yypvt[-1].Number * yypvt[-0].Number;
  1456.     } break;
  1457. case 34:
  1458. # line 287 "getdate.y"
  1459. {
  1460.         yyRelMonth += yypvt[-1].Number * yypvt[-0].Number;
  1461.     } break;
  1462. case 35:
  1463. # line 290 "getdate.y"
  1464. {
  1465.         yyRelMonth += yypvt[-0].Number;
  1466.     } break;
  1467. case 36:
  1468. # line 295 "getdate.y"
  1469. {
  1470.         if (yyHaveTime && yyHaveDate && !yyHaveRel)
  1471.         yyYear = yypvt[-0].Number;
  1472.         else {
  1473.         if(yypvt[-0].Number>10000) {
  1474.             time_t date_part;
  1475.  
  1476.             date_part= yypvt[-0].Number/10000;
  1477.             yyHaveDate++;
  1478.             yyDay= (date_part)%100;
  1479.             yyMonth= (date_part/100)%100;
  1480.             yyYear = date_part/10000;
  1481.         } 
  1482.             yyHaveTime++;
  1483.         if (yypvt[-0].Number < 100) {
  1484.             yyHour = yypvt[-0].Number;
  1485.             yyMinutes = 0;
  1486.         }
  1487.         else {
  1488.             yyHour = yypvt[-0].Number / 100;
  1489.             yyMinutes = yypvt[-0].Number % 100;
  1490.         }
  1491.         yySeconds = 0;
  1492.         yyMeridian = MER24;
  1493.         }
  1494.     } break;
  1495. case 37:
  1496. # line 323 "getdate.y"
  1497. {
  1498.         yyval.Meridian = MER24;
  1499.     } break;
  1500. case 38:
  1501. # line 326 "getdate.y"
  1502. {
  1503.         yyval.Meridian = yypvt[-0].Meridian;
  1504.     } break;
  1505.     }
  1506.     goto yystack;        /* reset registers in driver code */
  1507. }
  1508.